import base64
import hashlib
import json
import random
import time

import jwt
from django.core import mail
from django.http import JsonResponse
# from django.views import View
from django.core.cache import caches
from django.db import transaction

from utils.smsapi import send_message
from .models import UserProfile, Address
from django.conf import settings

# from utils.logging_dec import logging_check
from utils.baseview import BaseView


def register_view(request):
    """
    注册功能的视图逻辑
    1.获取请求体数据(用户名、密码、邮箱、手机号)
    2.数据合法性校验
        用户名6-11,密码6-12,手机号11位
    3.判断用户名是否被占用
        被占用直接返回
        未占用，存入用户表，生成token，返回相应(API文档)
    """
    data = json.loads(request.body)
    username = data.get("uname")
    password = data.get("password")
    phone = data.get("phone")
    email = data.get("email")
    # 短信验证码
    verify = data.get("verify")

    # 验证码校验
    key_expire = f"sms_{phone}_verify"
    redis_num = caches["sms_code"].get(key_expire)
    if not redis_num:
        # 过期
        return JsonResponse({"code": 10114, "error": "验证码过期"})

    if verify != str(redis_num):
        return JsonResponse({"code": 10115, "error": "验证码错误"})

    # 数据合法性校验
    if len(username) < 2 or len(username) > 11:
        return JsonResponse({"code": 10100, "error": "用户名不合法"})
    if len(password) < 6 or len(password) > 12:
        return JsonResponse({"code": 10101, "error": "手机号不合法"})

    user_query = UserProfile.objects.filter(username=username)
    if user_query:
        return JsonResponse({"code": 10103, "error": "用户名被占用"})

    # 存入数据表
    pwd_md5 = md5_func(password)
    user = UserProfile.objects.create(username=username, password=pwd_md5, email=email, phone=phone)
    # 发送激活邮件
    # 对用户标识进行加密
    code_num = random.randint(1000, 9999)
    code_str = f"{code_num}_{username}"
    code = base64.b64encode(code_str.encode()).decode()

    verify_url = f"http://127.0.0.1:7000/dadashop/templates/active.html?code={code}"
    send_active_email(email, username, verify_url)

    # 存入Redis : {"active_username": 1016}
    key = f"active_{username}"
    caches["default"].set(key, code_num, 86400)

    token = make_token(username)
    result = {
        'code': 200,
        'username': username,
        'token': token,
        'carts_count': 0
    }
    return JsonResponse(result)


def login_view(request):
    """
    逻辑：
        1、获取数据
        2、校验密码
    """
    data = json.loads(request.body)
    username = data.get("username")
    password = data.get("password")

    try:
        user_query = UserProfile.objects.get(username=username)
    except Exception as e:
        return JsonResponse({"code": 10104, "error": "用户名错误"})

    if user_query.password != md5_func(password):
        return JsonResponse({"code": 10105, "error": "用户名或密码错误"})
    token = make_token(username)
    result = {
        'code': 200,
        'username': username,
        'token': token,
        'carts_count': 0
    }
    return JsonResponse(result)


class AddressView(BaseView):
    """
    FBV
    """
    # def dispatch(self, request, *args, **kwargs):
    #     # 转发调度
    #     # 登陆装饰的校验
    #     # 可以替换装饰器
    #     return super().dispatch(request, *args, **kwargs)

    # @logging_check
    def get(self, request, username):
        """
        查询收货地址
        """
        user = request.myuser
        add_query = Address.objects.filter(
            user_profile=user, is_delete=False
        )
        addresslist = []
        for addr in add_query:
            add_dict = {
                'id': addr.id,
                'address': addr.address,
                'receiver': addr.receiver,
                'receiver_mobile': addr.receiver_mobile,
                'tag': addr.tag,
                'postcode': addr.postcode,
                'is_default': addr.is_default,
            }
            addresslist.append(add_dict)
        return JsonResponse({"code": 200, "addresslist": addresslist})

    # @logging_check
    def post(self, request, username):
        """
        地址视图逻辑
            获取请求体数据
            存入数据表
                第一个地址：新增并设置为默认
                非第一个地址：新增为非默认地址
            返回相应
        """
        print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
        data = json.loads(request.body)
        receiver = data.get("receiver")
        receiver_phone = data.get("receiver_phone")
        address = data.get("address")
        postcode = data.get("postcode")
        tag = data.get("tag")

        user = request.myuser
        addr_query = Address.objects.filter(user_profile=user, is_delete=False)
        is_default = False if addr_query else True

        # 存地址
        Address.objects.create(
            user_profile=user,
            receiver=receiver,
            address=address,
            postcode=postcode,
            receiver_mobile=receiver_phone,
            tag=tag,
            is_default=is_default,
        )
        return JsonResponse({"code": 200, "data": "新增地址成功"})

    # @logging_check
    def put(self, request, username, id):
        """
        修改地址视图逻辑
        """
        data = json.loads(request.body)
        receiver = data.get("receiver")
        receiver_mobile = data.get("receiver_mobile")
        address = data.get("address")
        tag = data.get("tag")
        user = request.myuser
        try:
            addr = Address.objects.get(user_profile=user, id=id, is_delete=False)
        except Exception as e:
            return JsonResponse({"code": 10107, "error": "该地址不存在"})
        addr.receiver = receiver
        addr.receiver_mobile = receiver_mobile
        addr.address = address
        addr.tag = tag
        addr.save()
        return JsonResponse({"code": 200, "data": "地址修改成功"})

    # @logging_check
    def delete(self, request, username, id):
        """
        删除地址试图逻辑（伪删除）
        """
        user = request.myuser
        try:
            addr = Address.objects.get(user_profile=user, id=id, is_delete=False)
        except Exception as e:
            return JsonResponse({"code": 10106, "error": "该地址不存在"})

        addr.is_delete = True
        addr.save()
        return JsonResponse({"code": 200, "data": "删除地址成功"})


class DefaultAddressView(BaseView):
    # @logging_check
    def post(self, request, username):
        """
        设置默认地址
        1.获取请求体数据
        2.两个ORM更新操作
            把原来的取消
            把现在的地址设置为默认
        """
        data = json.loads(request.body)
        addr_id = data.get("id")
        user = request.myuser
        # 开启事物
        with transaction.atomic():
            sid = transaction.savepoint()
            try:
                # 原来的地址取消默认
                old_query = Address.objects.filter(
                    user_profile=user,
                    is_default=True,
                    is_delete=False
                )
                if old_query:
                    old_user = old_query[0]
                    old_user.is_default = False
                    old_user.save()

                # 现在的设为默认
                now_user = Address.objects.get(
                    id=addr_id,
                    user_profile=user,
                    is_delete=False
                )
                now_user.is_default = True
                now_user.save()
            except Exception as e:
                transaction.savepoint_rollback(sid)
                return JsonResponse({"code": 10108, "error": "确定默认失败"})
            transaction.savepoint_commit(sid)
            # 返回相应
            return JsonResponse({"code": 200, "data": "设置默认地址成功"})


def active_view(request):
    """
    邮件激活视图逻辑
    """
    code = request.GET.get("code")
    code_str = base64.b64decode(code.encode()).decode()
    user_num, username = code_str.split("_")
    key = f"active_{username}"
    redis_unm = caches["default"].get(key)
    if not redis_unm:
        return JsonResponse({"code": 10109, "error": "激活失败"})
    if user_num != str(redis_unm):
        return JsonResponse({"code": 10110, "error": "激活码错误"})
    try:
        user = UserProfile.objects.get(username=username, is_active=False)
    except Exception as e:
        return JsonResponse({"code": 10111, "error": "该用户不存在"})

    user.is_active = True
    user.save()

    # 释放内存,清除激活数据
    caches["default"].delete(key)

    return JsonResponse({"code": 200, "data": "激活用户成功"})


def sms_view(request):
    """发送短信验证码"""
    data = json.loads(request.body)
    phone = data.get("phone")
    code_num = random.randint(100000, 999999)
    key = f"sms_{phone}"
    redis_num = caches["sms_code"].get(key)
    if redis_num:
        return JsonResponse({"code": "10133", "error": "短信发送过于频繁"})

    datas = (code_num, 5)
    send_message("1", phone, datas)

    # 存入redis
    caches["sms_code"].set(key, code_num, 60)

    key_verify = f"sms_{phone}_verify"
    caches["sms_code"].set(key_verify,code_num, 300)

    return JsonResponse({"code": "200", "data": "短信发送成功"})


def md5_func(string):
    """
    功能函数: md5加密函数
    """
    m = hashlib.md5()
    m.update(string.encode())
    return m.hexdigest()


def make_token(username, expire=86400):
    """
    功能函数：生成token
    """
    payload = {
        "exp": int(time.time()) + expire,
        "username": username
    }
    key = settings.JWT_TOKEN_KEY

    # jwt.encode()生成byte对象，不是string无法转换成json
    return str(jwt.encode(payload=payload, key=key, algorithm="HS256"))


def send_active_email(email, username, verify_url):
    """
    功能函数: 发送邮件
    """
    subject = "大大商城激活邮件"
    message = f"""
欢迎您:{username},请点击激活连接进行激活:<a href="{verify_url}" target="_blank">点击此处</a>
"""
    mail.send_mail(
        subject=subject,
        message="",
        from_email=settings.EMAIL_HOST_USER,
        recipient_list=[email],
        html_message=message
    )
